package sg.edu.nus.iss.billing.gui;

import java.awt.BorderLayout;
import java.awt.Font;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.GridLayout;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.FileInputStream;
import java.util.Properties;

import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JPasswordField;
import javax.swing.JTextField;
import javax.swing.SwingConstants;

import sg.edu.nus.iss.billing.BillingApplication;
import sg.edu.nus.iss.billing.BillingConstants;
import sg.edu.nus.iss.billing.BillingConstants.SystemState;
import sg.edu.nus.iss.billing.controller.UserController;
import sg.edu.nus.iss.billing.exceptions.ControllerException;
import sg.edu.nus.iss.billing.model.user.User;
import sg.edu.nus.iss.billing.model.user.User.SystemAcctStatus;
import sg.edu.nus.iss.billing.model.user.User.SystemRole;

/**
 * @author Yeo Hee Ling, Ananda, Saravana
 *
 */
public class UserPanel extends JPanel implements ActionListener {
	
	private static final long serialVersionUID = 1L;
	
	// Declaration of Global Variables.
	private User user;
	private Properties properties;
	private BillingApplication billingAppl;
	private JPanel searchResultPanel;
	private JLabel lblUsername, lblPassword, lblPersonName, lblSystemRole, lblSystemAcctStatus;
	private JTextField txtUsername, txtPersonName;
	private JPasswordField txtPassword;
	private JButton btnCreateUser, btnClear, btnEditUser, btnUpdateUser, btnSearchResult;
	private JComboBox cbSystemRole, cbSystemAcctStatus;
	private String[] systemRoleOption = {SystemRole.ADMIN.toString(), SystemRole.AGENT.toString()};
	private String[] systemAcctStatusOption = {SystemAcctStatus.Active.toString(), SystemAcctStatus.Suspended.toString()};
	
	// Class Constructor.
	public UserPanel(BillingApplication billingAppl, SystemState selectedMode, User user, JPanel searchResultPanel) {
		this.user = user;
		this.billingAppl = billingAppl;
		this.searchResultPanel = searchResultPanel;
		this.setOpaque(false);
		
		loadConfiguration();
		
		boolean editable = true;
		if(SystemState.SYSTEM_USER_VIEW == selectedMode)
			editable = false;
		
		JPanel customerPanel = new JPanel ();
		customerPanel.setOpaque(false);
        customerPanel.setLayout(new BorderLayout());
        customerPanel.add(createEditUserPanel(selectedMode, editable), BorderLayout.CENTER);
        
        if(SystemState.SYSTEM_USER_UPDATE == selectedMode || SystemState.SYSTEM_USER_VIEW == selectedMode) {
        	populateUserDetails();
        }
        
        add(customerPanel);
	}
	
	public void actionPerformed(ActionEvent e) {
		if(e.getSource() == btnCreateUser) {
			String personName = txtPersonName.getText().trim();
			String username = txtUsername.getText().trim();
			String password = new String(txtPassword.getPassword());
			SystemRole systemRole = SystemRole.valueOf(cbSystemRole.getSelectedItem().toString());
			
			try {
				UserController userController = new UserController();
				userController.createSystemUser(personName, username, password, systemRole);
				JOptionPane.showMessageDialog(this, properties.getProperty("info.message.createSuccessful"), properties.getProperty("title.createUser"), JOptionPane.INFORMATION_MESSAGE);				
				billingAppl.displayPage(new UserPanel(billingAppl, SystemState.SYSTEM_USER_CREATE, null, null));
			}
			catch(ControllerException ex) {
				JOptionPane.showMessageDialog(this, ex.getMessage(), properties.getProperty("title.createUser"), JOptionPane.ERROR_MESSAGE);
				return;
			}
		}
		else if(e.getSource() == btnUpdateUser) {
			try {
				user.setPersonName(txtPersonName.getText().trim());
				user.setPassword(new String(txtPassword.getPassword()));
				user.setSystemRole(SystemRole.valueOf(cbSystemRole.getSelectedItem().toString()));
				user.setSystemAcctStatus(SystemAcctStatus.valueOf(cbSystemAcctStatus.getSelectedItem().toString()));
				
				UserController userController = new UserController();
				userController.updateSystemUser(user);
				JOptionPane.showMessageDialog(this, properties.getProperty("info.message.updateSuccessful"), properties.getProperty("title.updateUser"), JOptionPane.INFORMATION_MESSAGE);
			}
			catch(ControllerException ex) {
				JOptionPane.showMessageDialog(this, ex.getMessage(), properties.getProperty("title.updateUser"), JOptionPane.ERROR_MESSAGE);
				return;
			}
		}
		else if(e.getSource() == btnEditUser) {
			billingAppl.displayPage(new UserPanel(billingAppl, SystemState.SYSTEM_USER_UPDATE, user, searchResultPanel));
		}
		else if(e.getSource() == btnSearchResult) {
			billingAppl.displayPage(searchResultPanel);
		}
		else if(e.getSource() == btnClear) {
			txtPersonName.setText("");
			txtUsername.setText("");
			txtPassword.setText("");
			cbSystemRole.setSelectedIndex(0);
		}
	}
	
	private void loadConfiguration() {
		try {
			properties = new Properties();
			FileInputStream in = new FileInputStream(BillingConstants.PROPERTIES_ADMINISTRATOR);
			properties.load(in);
			in.close();
		}
		catch(Exception ex) {
			ex.printStackTrace();
		}
	}
	
	private void populateUserDetails() {
		if(user != null) {
			txtPersonName.setText(user.getPersonName());
			txtUsername.setText(user.getUserName());
			txtUsername.setEditable(false);
			txtPassword.setText(user.getPassword());
			cbSystemRole.setSelectedItem(user.getSystemRole().toString());
			cbSystemAcctStatus.setSelectedItem(user.getSystemAcctStatus().toString());
		}
	}
	
	private JPanel createEditUserPanel(SystemState selectedMode, boolean editable) {
		// 1. To determine the title of the user panel.
		String administratorPanelTitle = "";
		if(SystemState.SYSTEM_USER_CREATE == selectedMode)
			administratorPanelTitle = properties.getProperty("label.admin.header.create");
		else if(SystemState.SYSTEM_USER_VIEW == selectedMode)
			administratorPanelTitle = properties.getProperty("label.admin.header.view");
		else if(SystemState.SYSTEM_USER_UPDATE == selectedMode)
			administratorPanelTitle = properties.getProperty("label.admin.header.update");
		
		// 2. Construct User Details Panel
		GridBagLayout userGridLayout = new GridBagLayout();
		GridBagConstraints constraints = new GridBagConstraints();
		constraints.insets = new Insets(5, 5, 5, 5);
		constraints.fill = GridBagConstraints.HORIZONTAL;
		
		JPanel userDetailPanel = new JPanel(userGridLayout);
		userDetailPanel.setOpaque(false);
		
		constraints.gridx = 0;
		constraints.gridy = 0;
		lblPersonName = new JLabel(properties.getProperty("label.admin.personName"));
		lblPersonName.setHorizontalAlignment(JLabel.RIGHT);
		userDetailPanel.add(lblPersonName, constraints);
		
		constraints.gridx = 1;
		constraints.gridy = 0;
		txtPersonName = new JTextField(20);
		txtPersonName.setEditable(editable);
		userDetailPanel.add(txtPersonName, constraints);
		
		constraints.gridx = 0;
		constraints.gridy = 1;
		lblUsername = new JLabel(properties.getProperty("label.admin.username"));
		lblUsername.setHorizontalAlignment(JLabel.RIGHT);
		userDetailPanel.add(lblUsername, constraints);
		
		constraints.gridx = 1;
		constraints.gridy = 1;
		txtUsername = new JTextField(20);
		txtUsername.setEditable(editable);
		userDetailPanel.add(txtUsername, constraints);
		
		constraints.gridx = 0;
		constraints.gridy = 2;
		lblPassword = new JLabel(properties.getProperty("label.admin.password"));
		lblPassword.setHorizontalAlignment(JLabel.RIGHT);
		userDetailPanel.add(lblPassword, constraints);
		
		constraints.gridx = 1;
		constraints.gridy = 2;
		txtPassword = new JPasswordField(20);
		txtPassword.setEditable(editable);
		userDetailPanel.add(txtPassword, constraints);
		
		constraints.gridx = 0;
		constraints.gridy = 3;
		lblSystemRole = new JLabel(properties.getProperty("label.admin.systemRole"));
		lblSystemRole.setHorizontalAlignment(JLabel.RIGHT);
		userDetailPanel.add(lblSystemRole, constraints);
		
		constraints.gridx = 1;
		constraints.gridy = 3;
		cbSystemRole = new JComboBox(systemRoleOption);
		cbSystemRole.setEnabled(editable);
		userDetailPanel.add(cbSystemRole, constraints);
		
		constraints.gridx = 0;
		constraints.gridy = 4;
		lblSystemAcctStatus = new JLabel(properties.getProperty("label.admin.systemAcctStatus"));
		lblSystemAcctStatus.setHorizontalAlignment(JLabel.RIGHT);
		userDetailPanel.add(lblSystemAcctStatus, constraints);
		
		constraints.gridx = 1;
		constraints.gridy = 4;
		cbSystemAcctStatus = new JComboBox(systemAcctStatusOption);
		cbSystemAcctStatus.setEnabled(editable);
		userDetailPanel.add(cbSystemAcctStatus, constraints);
		
		JPanel buttonPanel = new JPanel();
		buttonPanel.setOpaque(false);
		buttonPanel.setLayout(new GridLayout(0, 2, 5, 0));
		
		if(SystemState.SYSTEM_USER_CREATE == selectedMode) {
			cbSystemAcctStatus.setEnabled(false);
			
			btnCreateUser = new JButton(properties.getProperty("label.admin.button.create"));
			btnCreateUser.addActionListener(this);
			btnClear = new JButton(properties.getProperty("label.admin.button.clear"));
			btnClear.addActionListener(this);
			buttonPanel.add(btnCreateUser);
			buttonPanel.add(btnClear);
		}
		else if(SystemState.SYSTEM_USER_VIEW == selectedMode) {
			btnEditUser = new JButton(properties.getProperty("label.admin.button.editUser"));
			btnEditUser.addActionListener(this);
			btnSearchResult = new JButton(properties.getProperty("label.admin.button.searchResult"));
			btnSearchResult.addActionListener(this);
			buttonPanel.add(btnEditUser);
			buttonPanel.add(btnSearchResult);
		}
		else if(SystemState.SYSTEM_USER_UPDATE == selectedMode) {
			btnUpdateUser = new JButton(properties.getProperty("label.admin.button.updateUser"));
			btnUpdateUser.addActionListener(this);
			btnSearchResult = new JButton(properties.getProperty("label.admin.button.searchResult"));
			btnSearchResult.addActionListener(this);
			buttonPanel.add(btnUpdateUser);
			buttonPanel.add(btnSearchResult);
		}
		
		constraints.gridx = 1;
		constraints.gridy = 5;
		userDetailPanel.add(buttonPanel, constraints);
		
		// 3. Construct Header Panel
		JPanel headerPanel = new JPanel();
		headerPanel.setOpaque(false);
		headerPanel.setLayout(new GridLayout(0, 1, 10, 10));
		
		JLabel msgLabel = new JLabel(administratorPanelTitle);
		msgLabel.setFont(new Font("Tahoma", Font.BOLD, 18));
		msgLabel.setHorizontalAlignment(SwingConstants.CENTER);
		headerPanel.add(msgLabel);
		
		ImageIcon imgDivider = new ImageIcon("./images/divider.jpg");
		JLabel lblDivider = new JLabel(imgDivider);
		headerPanel.add(lblDivider);
		
		JPanel userPanel = new JPanel();
		userPanel.setOpaque(false);
		userPanel.setLayout(new BorderLayout());
		userPanel.add(headerPanel, BorderLayout.NORTH);
		userPanel.add(userDetailPanel, BorderLayout.CENTER);
		
		return userPanel;
	}
}
